import type { SearchSelectorConfig } from '../../../../module/page_enhancer/appearance/style_enhancement/platforms'
import type { SogouPageTypeResult } from './types'
import {
  SO_GOU_ENCYCLOPEDIA_HOSTNAME,
  SO_GOU_KNOWLEDGE_HOSTNAME,
  SO_GOU_VIDEO_HOSTNAME,
  SO_GOU_WEIXIN_HOSTNAME,
} from '../../../../types/constants'
import { PageRoute } from '../../../abstract/page_route'
import { SOGOU_SEARCH_PAGE_SELECTORS, SogouPageType } from './types'

export class SogouPage extends PageRoute {
  readonly name: string = 'SogouPage'
  private static instance: SogouPage
  get pageType(): SogouPageType | 'default' {
    return this.getCurrentPageMeta().type
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): SogouPage {
    if (!SogouPage.instance) {
      SogouPage.instance = new SogouPage()
    }
    return SogouPage.instance
  }

  /**
   * 获取结果选择器
   */
  getResultSelectors(pageType?: SogouPageType, includeHideElement: boolean = true): SearchSelectorConfig {
    return this.resultSelectors(
      {
        pageType: pageType || this.pageType,
        selectorConfig: SOGOU_SEARCH_PAGE_SELECTORS,
        includeHideElement,
        notSupportedPages: [
          SogouPageType.IndexSearch,
          SogouPageType.IndexWeixin,
          SogouPageType.IndexVideo,
          SogouPageType.IndexKnowledge,
          SogouPageType.NotFound,
          SogouPageType.Undefined,
        ],
      },
    )
  }

  /**
   * 获取当前页面类型
   */
  public getCurrentPageMeta(): SogouPageTypeResult {
    const url = this.getCurrentUrl()
    const path = new URL(url).pathname
    const hostname = new URL(url).hostname
    const params = new URLSearchParams(new URL(url).search)

    // 404 页面检测
    const notFoundResult = this.detectNotFoundPage(hostname)
    if (notFoundResult)
      return notFoundResult

    // 首页
    if (/^\/?$/.test(path)) {
      if (hostname === SO_GOU_WEIXIN_HOSTNAME) {
        return { type: SogouPageType.IndexWeixin }
      }
      else if (hostname === SO_GOU_VIDEO_HOSTNAME) {
        return { type: SogouPageType.IndexVideo }
      }
      else if (hostname === SO_GOU_KNOWLEDGE_HOSTNAME) {
        return { type: SogouPageType.IndexKnowledge }
      }
      else if (hostname === SO_GOU_ENCYCLOPEDIA_HOSTNAME) {
        return { type: SogouPageType.IndexEncyclopedia }
      }
      else {
        return { type: SogouPageType.IndexSearch }
      }
    }

    // 基础页面检测
    const pageResult = this.detectPages(path, params)
    if (pageResult)
      return pageResult

    // 未定义页面
    return { type: SogouPageType.Undefined }
  }

  /**
   * 检测 404 页面
   */
  private detectNotFoundPage(hostname: string): SogouPageTypeResult | null {
    const pageNotFoundRules = [
      /404.*Not Found/i, // 不区分大小写
      /页面不存在/,
    ]

    if (pageNotFoundRules.some(regex => regex.test(document.title))) {
      // 微信 404 页面
      if (hostname === SO_GOU_WEIXIN_HOSTNAME) {
        return { type: SogouPageType.WeixinNotFound }
      }

      return { type: SogouPageType.NotFound }
    }

    return null
  }

  /**
   * 检测其他功能页面
   */
  private detectPages(basePath: string, params: URLSearchParams): SogouPageTypeResult | null {
    const pageDetectors: Array<[RegExp, (...args: any[]) => SogouPageTypeResult]> = [
      [/^\/(sogou|web)\/?$/, () => {
        return this.detectSearchType(params)
      }],
      [/^\/weixin\/?$/, () => {
        return { type: SogouPageType.Weixin }
      }],
      [/^\/v\/?$/, () => {
        return { type: SogouPageType.Video }
      }],
      [/^\/docs\/more.htm\/?$/, () => {
        return { type: SogouPageType.More }
      }],
    ]

    for (const [regex, handler] of pageDetectors) {
      const match = basePath.match(regex)
      if (match) {
        return handler(match)
      }
    }

    return null
  }

  /**
   * 检测搜索类型
   */
  private detectSearchType(params: URLSearchParams): SogouPageTypeResult {
    const insite = params.get('insite')
    const m2web = params.get('m2web')
    const chuidq = params.get('chuidq')
    const interV = params.get('interV')

    if (insite === 'zhihu.com') {
      return { type: SogouPageType.Zhihu }
    }
    else if (insite === 'wenwen.sogou.com') {
      return { type: SogouPageType.Ask }
    }
    else if (insite === 'baike.sogou.com') {
      return { type: SogouPageType.Encyclopedia }
    }
    else if (m2web === 'mingyi.sogou.com') {
      return { type: SogouPageType.Medical }
    }
    else if (interV !== null && chuidq === null) {
      return { type: SogouPageType.News }
    }
    else if (chuidq !== null) {
      return { type: SogouPageType.Knowledge }
    }
    else {
      return { type: SogouPageType.Web }
    }
  }
}
